class MyPromise {
    constructor(executor) {
        this.status = "pending"
        this.data = null
        this.onResolvedCallbacks = []
        this.onRejectedCallbacks = []
        try {
            executor(this._resolve.bind(this), this._reject.bind(this))
        } catch (err) {
            this._reject(err)
        }
    }
    _resolve(value) {
        if (this.status === "pending") {
            this.status = "resolved"
            this.data = value
            for (const func of this.onResolvedCallbacks) {
                func(value)
            }
        }
    }
    _reject(reason) {
        if (this.status === "pending") {
            this.status = "rejected"
            this.data = reason
            for (const func of this.onRejectedCallbacks) {
                func(reason)
            }

        }
    }
    then(onResolved, onRejected) {
        onResolved = typeof onResolved === "function" ? onResolved : v => v
        onRejected = typeof onRejected === "function" ? onRejected : e => { throw e }
        let promise2 = new MyPromise((resolve, reject) => {
            if (this.status === "pending") {
                this.onResolvedCallbacks.push((value) => {
                    setTimeout(() => {
                        try {
                            const x = onResolved(value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (err) {
                            reject(err)
                        }
                    })
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(reason)
                        } catch (err) {
                            reject(err)
                        }
                    })
                })
            }
            if (this.status === "resolved") {
                setTimeout(() => {
                    try {
                        const x = onResolved(this.data)
                        this.resolvePromise(promise2, x, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                })
            }
            if (this.status === "rejected") {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.data)
                        this.resolvePromise(promise2, x, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                })
            }
        })
        return promise2
    }
    resolvePromise(promise2, x, resolve, reject) {
        let call = false
        if (x === promise2) {
            return reject(new TypeError("chaining cycle"))
        }
        else if (x instanceof MyPromise) {
            if (x.status === "pending") {
                // y --- 改变x状态的data this.data 调用onResolve函数时会传入this.data
                x.then((y) => {
                    this.resolvePromise(promise2, y, resolve, reject)
                }, reject)
            } else {
                // 传入resolve \ reject 改变promise2的状态
                x.then(resolve, reject)
            }
        }
        else if (x && (Object.prototype.toString.call(x) === "[object, Object]" || typeof x === "function")) {
            const then = x.then
            try {
                if (typeof then === "function") {
                    then.call(x, (y) => {
                        if (call) return
                        call = true
                        this.resolvePromise(promise2, y, resolve, reject)
                    }, reject)
                } else {
                    if (call) return
                    call = true
                    resolve(x)
                }
            } catch (err) {
                if (call) return
                call = true
                reject(err)
            }

        } else {
            resolve(x)
        }

    }
}